#include <gtk/gtk.h>
#include "demo.h"


static GtkTreeView *treeview;
static GtkBox *showBox;

static DemoInfo widgetDemos[]=
{
  {NULL, "root", "widget demo", NULL},
  {NULL, "button box", "GtkButtonBox", do_button_box},
  {NULL, "label", "GtkLabel", do_label},
  {NULL, "image", "GtkImage", do_image},
  {NULL, "spinner", "GtkSpinner", do_spinner},
  {NULL, "infobar", "GtkInfoBar", do_infobar},
  {NULL, "button", "buttons", do_button},
  {NULL, "progressbar", "GtkProgressBar", do_progressbar},
  {NULL, "levelbar", "GtkLevelBar", do_levelbar},
  {NULL, "statusbar", "GtkStatusBar", do_statusbar},
  {NULL, "entry", "GtkEntry", do_entry},
  {NULL, "scale", "GtkScale", do_scale},
  {NULL, "scrollbar", "GtkScrollbar", do_scrollbar},
  {NULL, "spinbutton", "GtkSpinButton", do_spinbutton},
  {NULL, "calendar", "GtkCalendar", do_calendar},
  {NULL, "dialogs", "dialogs", do_dialogs},
  {NULL, "combobox", "GtkComboBox", do_combobox},
  {NULL, "treeview", "GtkTreeView", do_treeview},
  {NULL, "popover", "GtkPopover", do_popover},
  // {NULL, "", "", NULL},
  // {NULL, "", "", NULL},
  // {NULL, "", "", NULL},
  {NULL}  
};


//popup about dialog
static void activate_about (GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
    GtkApplication *app = user_data;
    const gchar *authors[] = {
        "zcatt",
        NULL
    };

  gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
                         "program-name", "a05_widgetDemo",
                         "version", g_strdup_printf ("%s,\nRunning against GTK+ %d.%d.%d",
                                                     "1.0.0",
                                                     gtk_get_major_version (),
                                                     gtk_get_minor_version (),
                                                     gtk_get_micro_version ()),
                         "license-type", GTK_LICENSE_LGPL_2_1,
                         "comments", "Program to demonstrate GTK+ widgets derived from gtk3-demo.",
                         "authors", authors,
                         //"logo-icon-name", "gtk3-demo",
                         "title", "About a05_widgetDemo",
                         NULL);
}

//quit app
static void activate_quit (GSimpleAction *action, GVariant *parameter, gpointer user_data)
{
  GtkApplication *app = user_data;
  GtkWidget *win;
  GList *list, *next;

  list = gtk_application_get_windows (app);
  while (list)
    {
      win = list->data;
      next = list->next;

      gtk_widget_destroy (GTK_WIDGET (win));

      list = next;
    }
}


//app startup callback
static void startup (GApplication *app)
{
  GtkBuilder *builder;
  GMenuModel *appmenu;
  gchar *ids[] = { "appmenu", NULL };

  builder = gtk_builder_new ();
  gtk_builder_add_objects_from_resource (builder, "/a05_widgetDemo/appmenu.ui", ids, NULL);

  appmenu = (GMenuModel *)gtk_builder_get_object (builder, "appmenu");

  gtk_application_set_app_menu (GTK_APPLICATION (app), appmenu);

  g_object_unref (builder);
}

static gboolean insert_foreach(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
  gboolean res = FALSE;     //continue to search
  DemoInfo *p = data;
  gchar* name; 

  g_print("insert_foreach.....\n");

  g_assert(p->name);
  gtk_tree_model_get(model, iter
                  , NAME_COLUMN, &name
                  , -1);

  if(strcmp(name, p->parent) == 0)
  {
    g_print("found parent %s\n", name);
    GtkTreeIter cur;
    gtk_tree_store_append(GTK_TREE_STORE(model), &cur, iter);
    gtk_tree_store_set(GTK_TREE_STORE(model)
                        , &cur
                        , NAME_COLUMN, p->name
                        , TITLE_COLUMN, p->title
                        , FUNC_COLUMN, p->func
                        , STYLE_COLUMN, PANGO_STYLE_NORMAL
                        , -1);
    
    res = TRUE;   //stop search
  }

  g_free(name);

  return res;
}


//填充treeview
static void populate_model (GtkTreeModel *model)
{  
    DemoInfo *p = widgetDemos;

    while(p->title)  
    {
      if(p->parent)
      {
        gtk_tree_model_foreach(model, insert_foreach, p);
      }
      else
      {   //toplevel
        GtkTreeIter iter;
        gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
        gtk_tree_store_set(GTK_TREE_STORE(model)
                            , &iter
                            , NAME_COLUMN, p->name
                            , TITLE_COLUMN, p->title
                            , FUNC_COLUMN, p->func
                            , STYLE_COLUMN, PANGO_STYLE_NORMAL
                            , -1);
      }

      p++;
    }
}

static void clear_show_box(void)
{
    GList *list;
    GList *next;
    list = gtk_container_get_children(GTK_CONTAINER(showBox));
    while(list)
    {
      next = list->next;
      gtk_widget_destroy(GTK_WIDGET(list->data));

      list = next;
    }

}

//选中tree node的callback
static void cursor_changed_cb(GtkTreeView *tree_view, gpointer user_data)
{
    GtkTreePath *path;
    GtkTreeIter iter;


    g_print("cursor_changed_cb.....\n");
    
    gtk_tree_view_get_cursor (tree_view, &path, NULL);
    
    if(!path)
      return;

    GtkTreeModel *model;
    model = gtk_tree_view_get_model (tree_view);
    gtk_tree_model_get_iter (model, &iter, path);
    gtk_tree_path_free(path);

    DemoFunc func;
    PangoStyle style;
    gtk_tree_model_get(model, &iter
                        , FUNC_COLUMN, &func
                        , STYLE_COLUMN, &style
                        , -1);

    //clear old
    clear_show_box();

    //create the demo
    if(func)
    {
      g_print("demoFunc().....\n");
      gtk_tree_store_set (GTK_TREE_STORE (model),
                          &iter,
                          STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
                          -1);
      (func)(showBox);
    }
}

#if 0
//双击选中tree node的callback
static void row_activated_cb (GtkWidget *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
{
    GtkTreeIter iter;
    GtkTreeModel *model;

    g_print("row_activated_cb.....\n");
    
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
    gtk_tree_model_get_iter (model, &iter, path);

    DemoFunc func;
    PangoStyle style;

    gtk_tree_model_get(model, &iter
                        , FUNC_COLUMN, &func
                        , STYLE_COLUMN, &style
                        , -1);

    //clear old
    clear_show_box();

    //create the demo
    if(func)
    {
      g_print("demoFunc().....\n");
      gtk_tree_store_set (GTK_TREE_STORE (model),
                          &iter,
                          STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
                          -1);
      (func)(showBox);
    }
}
#endif

//选中tree node的callback
static void selection_cb (GtkTreeSelection *selection, gpointer user_data)
{
  // GtkTreeModel *model = user_data;

  g_print("selection_cb()....\n");
}


//app activate callback
static void activate (GApplication *app)
{
    GtkBuilder *builder;
    GtkWindow *window;
    GtkWidget *widget;
    GtkTreeModel *model;
    GtkTreeIter iter;
    GError *error = NULL;

    builder = gtk_builder_new ();
    gtk_builder_add_from_resource (builder, "/a05_widgetDemo/main.ui", &error);
    if (error != NULL)
    {
        g_critical ("%s", error->message);
        exit (1);
    }

    window = (GtkWindow *)gtk_builder_get_object (builder, "appWin");
    gtk_application_add_window (GTK_APPLICATION (app), window);

    // static GActionEntry win_entries[] = {
    //     { "run", activate_run, NULL, NULL, NULL }
    // };

    // g_action_map_add_action_entries (G_ACTION_MAP (window),
    //                             win_entries, G_N_ELEMENTS (win_entries),
    //                             window);

    treeview = (GtkTreeView *)gtk_builder_get_object (builder, "treeview");
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));

    showBox = (GtkBox *)gtk_builder_get_object (builder, "showBox");

    populate_model(model);

    g_signal_connect(treeview, "cursor_changed", G_CALLBACK(cursor_changed_cb), NULL);
    //g_signal_connect(treeview, "row-activated", G_CALLBACK(row_activated_cb), model);

    widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
    g_assert(widget);
    g_signal_connect(widget, "changed", G_CALLBACK(selection_cb), model);

    gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);

    GtkTreeIter next = iter;
    while(gtk_tree_model_iter_next(model, &next))
    {
      iter = next;
    }

    GtkTreePath *path;
    path = gtk_tree_model_get_path(model, &iter);
    if(path)
    {
      //触发cursor_changed signal, 调用cursor_changed_cb回调.
      gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview), path, NULL, FALSE);
      gtk_tree_path_free(path);
    }


    gtk_tree_selection_select_iter (GTK_TREE_SELECTION(widget), &iter);

    //gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
    gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));

    gtk_widget_show_all (GTK_WIDGET (window));

    g_object_unref (builder);
}


int main(int argc, char* argv[])
{
    GtkApplication *app;

    app = gtk_application_new("com.zcatt.a05_widgetDemo", G_APPLICATION_FLAGS_NONE);

    static GActionEntry app_entries[] = {
            { "about", activate_about, NULL, NULL, NULL },
            { "quit", activate_quit, NULL, NULL, NULL },
        };
    g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), app);

    g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

    g_application_run(G_APPLICATION(app), 0, 0);

    return 0;
}